//package algorithms.encryption.rsa;
//
//import algorithms.encryption.aes.AESUtil;
//
//import javax.crypto.Cipher;
//import java.io.ByteArrayOutputStream;
//import java.io.IOException;
//import java.nio.charset.StandardCharsets;
//import java.security.*;
//import java.security.interfaces.RSAPrivateKey;
//import java.security.interfaces.RSAPublicKey;
//import java.security.spec.PKCS8EncodedKeySpec;
//import java.security.spec.X509EncodedKeySpec;
//import java.util.*;
//
//public class RSAUtil {
//    /**
//     * 编码格式
//     */
//    private static final String CHARSET = "UTF-8";
//
//    private static final String RSA = "RSA";
//    /**
//     * base64编码
//     *
//     * @param data
//     * @return
//     */
//    private static String encode(byte[] data) {
//        return Base64.encodeBase64String(data);
//    }
//
//    /**
//     * base64解码
//     *
//     * @param data
//     * @return
//     */
//    private static byte[] decode(String data) {
//        return Base64.decodeBase64(data);
//    }
//
//    /**
//     * 获取一对公钥，私钥
//     *
//     * @return Map : publicKey:公钥，privateKey：私钥
//     * @throws NoSuchAlgorithmException
//     */
//    public static Map<String, String> getRSAPublicKeyAndPrivateKey() throws NoSuchAlgorithmException {
//        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
//        keyPairGenerator.initialize(1024);
//        KeyPair keyPair = keyPairGenerator.generateKeyPair();
//        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();           //公钥
//        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();       //私钥
//        Map<String, String> keyMap = new HashMap<>();
//        String publicKey = encode(rsaPublicKey.getEncoded());
//        String privateKey = encode(rsaPrivateKey.getEncoded());
//        keyMap.put("publicKey", publicKey);
//        keyMap.put("privateKey", privateKey);
//        return keyMap;
//    }
//
//    /**
//     * 获取私钥对象
//     *
//     * @param privateKey
//     * @return
//     * @throws Exception
//     */
//    private static PrivateKey getPrivateKey(String privateKey) throws Exception {
//        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode(privateKey));
//        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
//        return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//    }
//
//    /**
//     * 获取公钥对象
//     *
//     * @param publicKey
//     * @return
//     * @throws Exception
//     */
//    private static PublicKey getPublicKey(String publicKey) throws Exception {
//        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode(publicKey));
//        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
//        return keyFactory.generatePublic(x509EncodedKeySpec);
//    }
//
//    /**
//     * RAS公钥加密
//     *
//     * @param pubKey base64公钥
//     * @param data   原始数据
//     * @return 加密后的base64
//     */
//    public static String encryptByPublicKey(String pubKey, String data) throws Exception {
//        PublicKey publicKey = getPublicKey(pubKey);
//        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//        byte[] output = blockCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET));
//        return encode(output);
//    }
//
//    /**
//     * RSA私钥解密
//     *
//     * @param priKey base64私钥
//     * @param data   加密后的base64
//     * @return 原始数据
//     */
//    public static String decryptByPrivateKey(String priKey, String data) throws Exception {
//        PrivateKey privateKey = getPrivateKey(priKey);
//        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//        cipher.init(Cipher.DECRYPT_MODE, privateKey);
//        byte[] output = blockCodec(cipher, Cipher.DECRYPT_MODE, decode(data));
//        return new String(output, CHARSET);
//    }
//
//    /**
//     * 数据分段加解密
//     *
//     * @param cipher
//     * @param mode
//     * @param dataByte
//     * @return
//     * @throws IOException
//     */
//    private static byte[] blockCodec(Cipher cipher, int mode, byte[] dataByte) throws IOException {
//        int maxBlock;
//        if (mode == Cipher.DECRYPT_MODE) {
//            maxBlock = 128;
//        } else {
//            maxBlock = 117;
//        }
//        ByteArrayOutputStream out = new ByteArrayOutputStream();
//        int offSet = 0;
//        byte[] buff;
//        int i = 0;
//        try {
//            while (dataByte.length > offSet) {
//                if (dataByte.length - offSet > maxBlock) {
//                    buff = cipher.doFinal(dataByte, offSet, maxBlock);
//                } else {
//                    buff = cipher.doFinal(dataByte, offSet, dataByte.length - offSet);
//                }
//                out.write(buff, 0, buff.length);
//                i++;
//                offSet = i * maxBlock;
//            }
//            byte[] resultBytes = out.toByteArray();
//            return resultBytes;
//        } catch (Exception e) {
//            throw new RuntimeException("加解密块大小为[" + maxBlock + "]时发生异常", e);
//        } finally {
//            out.close();
//        }
//    }
//
//    /**
//     * 生成签名
//     *
//     * @param data   签名数据
//     * @param priKey base64私钥
//     * @return 签的base64
//     */
//    public static String sign(byte[] data, String priKey) throws Exception {
//        PrivateKey privateKey = getPrivateKey(priKey);
//        Signature signature = Signature.getInstance("SHA256WithRSA");
//        signature.initSign(privateKey);
//        signature.update(data);
//        byte[] sign = signature.sign();
//        return encode(sign);
//    }
//
//
//    /**
//     * 验证签名
//     *
//     * @param data   签名数据
//     * @param sign   签的base64
//     * @param pubKey base64公钥
//     * @return 验证签名结果
//     */
//    public static boolean verify(String data, String sign, String pubKey) throws Exception {
//        PublicKey publicKey = getPublicKey(pubKey);
//        Signature signature = Signature.getInstance("SHA256WithRSA");
//        signature.initVerify(publicKey);
//        signature.update(data.getBytes(CHARSET));
//        return signature.verify(decode(sign));
//    }
//
//    /**
//     * 创建签名
//     *
//     * @param params
//     * @return
//     */
//    public static String createSignStr(Map<String, Object> params) {
//        params.remove("sign");
//        //  注意必须是TreeMap,TreeMap保证key是升序的
//        TreeMap<String, Object> treeMap = new TreeMap<>(params);
//        return map2str(treeMap);
//    }
//
//    /**
//     * map转String key=value&形式
//     *
//     * @param map
//     * @return
//     */
//    private static String map2str(TreeMap<String, Object> map) {
//        List<String> values = new ArrayList<>();
//        for (Map.Entry<String, Object> entry : map.entrySet()) {
//            values.add(entry.getKey() + "=" + entry.getValue());
//        }
//        return String.join("&", values);
//    }
//
//    public static void main(String[] args) throws Exception {
//        //genKey();
//        // RSA加密解密
//       //demo();
//        // AES+RSA+RSA签名验签
//        signDemo();
//    }
//
//    private static void signDemo() throws Exception {
//        String serverPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDt9ssOYlPr+baUcfnCJK43eYa+XBtWykXao/nml58BlYOTHOa9GtXkkrq1/Y5z0uV9/l3DNTjPgKLa9Y/71AyCUxOcpK8eUfiXOh5LnRE/8ht78qhlNVHIvWEXDmB2A98dam4ciox0ar1QbuRZPwyLhyBJJvLcf9aWSRf+Z9YNUQIDAQAB";
//        String serverPrivateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAO32yw5iU+v5tpRx+cIkrjd5hr5cG1bKRdqj+eaXnwGVg5Mc5r0a1eSSurX9jnPS5X3+XcM1OM+Aotr1j/vUDIJTE5ykrx5R+Jc6HkudET/yG3vyqGU1Uci9YRcOYHYD3x1qbhyKjHRqvVBu5Fk/DIuHIEkm8tx/1pZJF/5n1g1RAgMBAAECgYAxSIyTZQ/mbmg+5EAK0lf2i0e5ww+ycN/4wT8vX7WBuXpvjGvJPHaSCUV8DZBkMohvCLBYjnw+lXClEniIeklAijhRWQlYukVrFXJvSncIHO1Pq4XmEEhhZkgKqlvQrroojqf7apFZC4tbE8FUZpYJ3yP33GqP04LUsMwYAmb/9QJBAP2TGXEtwwMaLgBY66qUBQRgg4V1AUu4COIM/KVpDooP7qIiElf12VGh1XrAQxiHqtWdlMuNlM3Vz+zWVgJthTcCQQDwPXhK+V+dl3yxVvyIbYbmwz03Nbyhj+j2EKhGVB+8v/m2DF0jRxOQraj0GHcY8yFdQvknk5kZENwFEPZgfEW3AkB2pQUad5bvNKihcPmTbn6Kdb4UC5L3orxFSF5N5sHux1WYduiuT1HHaDlCngLGz3OXT4v3Ud92D7yhzAeiSywxAkAiYmnpMTACOkBakXyreiGovaDxWfuZlCNftJqhFkFEnqV67OIXvoCKYJCh/y5sn7/SvVcz1ug+si8LepYI0UCZAkANg/rnJbV2sZqvwTiqe5pQGmY82eVgLOkxr/qROEF8HiNEPo+E/1zC9L57oGC1G+xfQ+HLx0xIhwV2x9LH6WkZ";
//        String clientPubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUQt4y3zsSr6AB0pUPndjOyYfF/zvxavLvi7/9uX0OYi4MKz5UOQuPzJC4BlZiiTmOv4xcJ+nwF7oagk3cMZfZ8V5YSuj9EFW5X1E1ZUGoWCNGBxX/KQOOFejQm4r3KGm5X531S/yaWg/9nYxo1G9lpR1V4yyISzPfCelfMZ2ZPQIDAQAB";
//        String clientPriKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANRC3jLfOxKvoAHSlQ+d2M7Jh8X/O/Fq8u+Lv/25fQ5iLgwrPlQ5C4/MkLgGVmKJOY6/jFwn6fAXuhqCTdwxl9nxXlhK6P0QVblfUTVlQahYI0YHFf8pA44V6NCbivcoablfnfVL/JpaD/2djGjUb2WlHVXjLIhLM98J6V8xnZk9AgMBAAECgYB0T9ACgGCWdLZxSTt1O0G6zqQf0yS9vaUxrpqeJi5o21PwRyH4dOno+mey74YWqKtplX0MYrLGZboNHKodpu9V9YYIrmhl9eSZ9PlRhh0ISUqSHhLSlGHNr4VfilwNtm46+yoX82zbM15MuZT0GEnH2oZb7idqYyEOB3nmWCci4QJBAP49R13yOeKtXtIlnmDXDfy8s5rmy68NnmbKPTLwiVzngPz4KSwXnFvckSV7k0/TPXQ3xcXqqRCyDTt3y/qSu8MCQQDVuyta6CHM61zvdrT2DjqBIg6C9eILsZoEo9uNIfwQFenY8fcHDYyP5cAhXuwe8ZWY/HE61MXjzLB/hFpX2gb/AkEAmArbmEJY/cfC0hgvPCjAM6pCGtv1aY3SchR2PvV8oHPOPvrF3JmOJ52jq+/YLD/fG5aTDwaD7vkcUrkU4phH8wJBAK5GBd4ENbtfltHzWy7e/zlYSbjjQUQDtvBdo6H6ugtrstggxCpOE/Upg3Yybhn1JuQtwy4TXKCYwLnZc8j6kIUCQQChrLkC8YPcH2+kmn2cUs4W4tU8s8+s7dECsw0BfYf8oS3nwtBjCXWTzxWXldsDEYwoGb35CssyWZIYxbh31Tjn";
//
//        String context = "123141sadxz";
//        String aesKey = AESUtil.genAESKey();
//
//        // =========客户端加密
//        Map<String, Object> map = new HashMap<>();
//        map.put("time",String.valueOf(System.currentTimeMillis()));
//        map.put("date",AESUtil.encrypt(context,aesKey));// 使用aes加密数据
//        map.put("key",encryptByPublicKey(serverPublicKey,aesKey));// 服务端公钥(RSA)对aesKey加密
//        map.put("sign",sign(createSignStr(map).getBytes(StandardCharsets.UTF_8), clientPriKey));// 客户端私钥(RSA)进行签名
//
//
//        // ========服务端解密
//        // 验签
//        String sign = (String) map.get("sign");
//        //map.put("time",String.valueOf(System.currentTimeMillis()));// 时间改变
//        boolean verify = verify(createSignStr(map), sign, clientPubKey);// 客户端公钥进行签名
//        //Assert.isTrue(verify,"验签失败!");
//
//        String aesKey1 = decryptByPrivateKey(serverPrivateKey, (String) map.get("key"));// 使用服务端私钥进行解密得到AESkey
//        System.out.println(aesKey.equals(aesKey1));
//        String context1 = AESUtil.decrypt((String) map.get("date"), aesKey1);// 使用AESkey解密
//        System.out.println(context1);
//        System.out.println(context1.equals(context));
//
//    }
//
//    private static void genKey() throws NoSuchAlgorithmException {
//        Map<String, String> publicKeyAndPrivateKey = getRSAPublicKeyAndPrivateKey();
//        System.out.println(publicKeyAndPrivateKey.get("publicKey"));
//        System.out.println(publicKeyAndPrivateKey.get("privateKey"));
//    }
//
//    private static void demo() throws Exception {
//        String test = "ZSj/OaEbHYa2kir21uD4enrWBZQdv6KOTRcnd2JItzb0LmJl1TKooZyAgCEYDBZglDMQYkwkjgBwvN2NapLAbQ==";
//        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDt9ssOYlPr+baUcfnCJK43eYa+XBtWykXao/nml58BlYOTHOa9GtXkkrq1/Y5z0uV9/l3DNTjPgKLa9Y/71AyCUxOcpK8eUfiXOh5LnRE/8ht78qhlNVHIvWEXDmB2A98dam4ciox0ar1QbuRZPwyLhyBJJvLcf9aWSRf+Z9YNUQIDAQAB";
//        String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAO32yw5iU+v5tpRx+cIkrjd5hr5cG1bKRdqj+eaXnwGVg5Mc5r0a1eSSurX9jnPS5X3+XcM1OM+Aotr1j/vUDIJTE5ykrx5R+Jc6HkudET/yG3vyqGU1Uci9YRcOYHYD3x1qbhyKjHRqvVBu5Fk/DIuHIEkm8tx/1pZJF/5n1g1RAgMBAAECgYAxSIyTZQ/mbmg+5EAK0lf2i0e5ww+ycN/4wT8vX7WBuXpvjGvJPHaSCUV8DZBkMohvCLBYjnw+lXClEniIeklAijhRWQlYukVrFXJvSncIHO1Pq4XmEEhhZkgKqlvQrroojqf7apFZC4tbE8FUZpYJ3yP33GqP04LUsMwYAmb/9QJBAP2TGXEtwwMaLgBY66qUBQRgg4V1AUu4COIM/KVpDooP7qIiElf12VGh1XrAQxiHqtWdlMuNlM3Vz+zWVgJthTcCQQDwPXhK+V+dl3yxVvyIbYbmwz03Nbyhj+j2EKhGVB+8v/m2DF0jRxOQraj0GHcY8yFdQvknk5kZENwFEPZgfEW3AkB2pQUad5bvNKihcPmTbn6Kdb4UC5L3orxFSF5N5sHux1WYduiuT1HHaDlCngLGz3OXT4v3Ud92D7yhzAeiSywxAkAiYmnpMTACOkBakXyreiGovaDxWfuZlCNftJqhFkFEnqV67OIXvoCKYJCh/y5sn7/SvVcz1ug+si8LepYI0UCZAkANg/rnJbV2sZqvwTiqe5pQGmY82eVgLOkxr/qROEF8HiNEPo+E/1zC9L57oGC1G+xfQ+HLx0xIhwV2x9LH6WkZ";
//        String encryptContext = encryptByPublicKey(publicKey, test);
//        System.out.println("加密："+encryptContext);
//        String context = decryptByPrivateKey(privateKey, encryptContext);
//        System.out.println("解密："+context);
//        System.out.println(test.equals(context));
//    }
//
//}
